import React, {FC, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState} from "react";
import {AxiosGet} from "../../services/HttpService.tsx";
import "./css/SelectTreeTransfer.less"
import useStateRef from "../../customUse/useStateRef.tsx";
import CTable from "../../global/table/CTable.tsx";
import {getObjByRule, treeMap} from "../../utils";
import {Button} from "antd";
import GlobalIcon from "../../global/GlobalIcon.tsx";

interface SelectTreeTransferProps {
    init?: any,
    view: string,
    otherProps: any,
    onChange?: Function,
    rowKey: string,
    value?: string,
    joinKey?: string,
    ds?: any,
    url?: string,
    dataSource?: any[],
    params?: any,
    format?: any,
    width?: number,
    height?: number,
    titles?: any[]
}

const SelectTreeTransfer: FC<SelectTreeTransferProps> = (props) => {
    const {
        joinKey = ",",
        rowKey = "id",
        dataSource,
        height,
        format = {
            key: "id",
            label: "zhCn|usEn|ptBr"
        }
    } = props;

    const leftDataRef = useRef([]),
        rightDataRef = useRef([]),
        leftTable = useRef(),
        rightTable = useRef();

    const [leftData, setLeftData] = useStateRef([], leftDataRef),
        [rightData, setRightData] = useStateRef([], rightDataRef),
        [isLeftDisabled, setIsLeftDisabled] = useState(true),
        [isRightDisabled, setIsRightDisabled] = useState(true);

    const getValue = useCallback(() => {
        const {ds = {}} = props;
        let newValue = ds.value || props.value;
        if (newValue) {
            newValue = newValue.split(joinKey);
        }
        return newValue || []
    }, [props.ds, props.value]);

    const loadData = useCallback(async () => {
        const {params = {}} = props;
        let options = [], selectKeys = getValue();
        if (dataSource) {
            options = dataSource;
        } else if (props.url) {
            const {data} = await AxiosGet(props.url, {
                ...params
            });
            options = data
        }
        let selectRwos = []
        const newData = treeMap(options, (children, item) => {
            const node = getObjByRule(item, format, true)
            if (selectKeys.includes(node[rowKey])) {
                if (!selectRwos.find(i => i[rowKey] === node[rowKey])) {
                    selectRwos.push(node);
                }
            }
            return {
                ...node,
                children: children.length ? children : null,
            }
        });
        setLeftData(newData);
        setRightData(selectRwos)
    }, [dataSource, props.value, props.ds, rowKey]);

    useEffect(() => {
        loadData()
    }, [dataSource, props.url, props.params]);

    useImperativeHandle(props.init, () => {
        return {
            getSelectRows: () => {
                return rightDataRef.current;
            }
        }
    })

    const handleLeftSelectChange = useCallback((rows) => {
        if (rows.length) {
            setIsLeftDisabled(false);
        } else {
            setIsLeftDisabled(true);
        }
    }, []);

    const isRowSelectable = useCallback((row) => {
        return !row.data.children
    }, [rowKey]);

    const rightSelectChange = useCallback((selectRows) => {
        setRightData(selectRows);
        props.onChange && props.onChange(selectRows.map(i => i[rowKey]));
    }, [rowKey]);

    const handleLeftClick = useCallback(() => {
        const selectRows = leftTable.current?.getTableSelectedRows();
        const dataMap = new Map();
        [...rightDataRef.current, ...selectRows].forEach(item => {
            dataMap.set(item[rowKey], item)
        });
        rightSelectChange(Array.from(dataMap.values()))
    }, [rowKey]);

    const handleRightClick = useCallback(() => {
        const selectRows = rightTable.current?.getTableSelectedRows() || [];
        const selectedKeys = new Set(selectRows.map(row => row[rowKey]));
        const newRightData = rightDataRef.current.filter(item => !selectedKeys.has(item[rowKey]));
        rightSelectChange(newRightData);
    }, [rowKey]);


    const handleRightSelectChange = useCallback((rows) => {
        if (rows.length) {
            setIsRightDisabled(false);
        } else {
            setIsRightDisabled(true);
        }
    }, []);

    const renderSelectLeftTreeTransfer = useMemo(() => {
        if (!leftData.length) {
            return
        }
        const {otherProps = {}, view} = props;
        return (
            <CTable
                {...otherProps}
                init={leftTable}
                hasCheckbox={true}
                dataSource={leftData}
                view={view}
                height={height}
                onSelectChange={handleLeftSelectChange}
                isRowSelectable={isRowSelectable}
            />
        )
    }, [props.view, props.otherProps, height, leftData]);

    const renderSelectRightTreeTransfer = useMemo(() => {
        const {otherProps = {}, view} = props;
        return (
            <CTable
                {...otherProps}
                init={rightTable}
                hasCheckbox={true}
                isTreeTable={false}
                isLazyData={false}
                view={view}
                dataSource={rightData}
                height={height}
                onSelectChange={handleRightSelectChange}
            />
        )
    }, [props.view, props.otherProps, height, rightData]);

    const renderSelectTreeTransfer = useMemo(() => {
        if (!leftData.length) {
            return
        }
        const {titles = ["待选列表", "已选列表"]} = props;
        return (
            <div className="sf_core_select_tree_transfer">
                <div className="sf_core_select_tree_transfer_left">
                    <div className="sf_core_select_tree_transfer_left_title">
                        {titles[0]}
                    </div>
                    {renderSelectLeftTreeTransfer}
                </div>
                <div className="sf_core_select_tree_transfer_btn">
                    <Button disabled={isLeftDisabled} type="primary" onClick={handleLeftClick}
                            icon={<GlobalIcon name="icon-right-move"/>}
                            size="small"/>
                    <Button disabled={isRightDisabled} type="primary" onClick={handleRightClick}
                            icon={<GlobalIcon name="icon-left-move"/>}
                            size="small"/>
                </div>
                <div className="sf_core_select_tree_transfer_right">
                    <div className="sf_core_select_tree_transfer_right_title">
                        {titles[1]}
                    </div>
                    {renderSelectRightTreeTransfer}
                </div>
            </div>
        )
    }, [props, leftData, rightData, isLeftDisabled, isRightDisabled]);

    return (renderSelectTreeTransfer);
};

export default React.memo(SelectTreeTransfer);